package cn.chiship.sdk.core.encryption;

import cn.chiship.sdk.core.exception.custom.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * AES加解密工具类
 *
 * @author lijian
 */
public class AesUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(AesUtil.class);

	private static final String ENCODE_RULES = "chiship";

	private AesUtil() {
	}

	/**
	 * 加密 1.构造密钥生成器 2.根据ecnodeRules规则初始化密钥生成器 3.产生密钥 4.创建和初始化密码器 5.内容加密 6.返回字符串
	 * @param content 内容
	 * @return 结果
	 */

	public static String aesEncode(String content) {
		try {
			// 1.构造密钥生成器，指定为AES算法,不区分大小写
			KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
			// 2.根据ecnodeRules规则初始化密钥生成器
			// 生成一个128位的随机源,根据传入的字节数组
			SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
			random.setSeed(ENCODE_RULES.getBytes());
			keyGenerator.init(128, random);
			// 3.产生原始对称密钥
			SecretKey originalKey = keyGenerator.generateKey();
			// 4.获得原始对称密钥的字节数组
			byte[] raw = originalKey.getEncoded();
			// 5.根据字节数组生成AES密钥
			SecretKey key = new SecretKeySpec(raw, "AES");
			// 6.根据指定算法AES自成密码器
			Cipher cipher = Cipher.getInstance("AES");
			// 7.初始化密码器，第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作，第二个参数为使用的KEY
			cipher.init(Cipher.ENCRYPT_MODE, key);
			// 8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
			byte[] byteEncode = content.getBytes(StandardCharsets.UTF_8);
			// 9.根据密码器的初始化方式--加密：将数据加密
			byte[] byteAes = cipher.doFinal(byteEncode);
			// 10.将加密后的数据转换为字符串
			// 这里用Base64Encoder中会找不到包
			// 解决办法：
			// 在项目的Build path中先移除JRE System Library，再添加库JRE System Library，重新编译后就一切正常了。
			// 11.将字符串返回
			return new String(Base64.getEncoder().encode(byteAes));
		}
		catch (Exception e) {
			LOGGER.error("发生异常", e);
		}
		// 如果有错就返加nulll
		return null;
	}

	/**
	 * 解密 解密过程： 1.同加密1-4步 2.将加密后的字符串反纺成byte[]数组 3.将加密内容解密
	 * @param content 内容
	 * @return 结果
	 */
	public static String aesDecode(String content) {
		try {
			// 1.构造密钥生成器，指定为AES算法,不区分大小写
			KeyGenerator keygen = KeyGenerator.getInstance("AES");
			// 2.根据ecnodeRules规则初始化密钥生成器
			// 生成一个128位的随机源,根据传入的字节数组
			SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
			random.setSeed(ENCODE_RULES.getBytes());
			keygen.init(128, random);
			// 3.产生原始对称密钥
			SecretKey originalKey = keygen.generateKey();
			// 4.获得原始对称密钥的字节数组
			byte[] raw = originalKey.getEncoded();
			// 5.根据字节数组生成AES密钥
			SecretKey key = new SecretKeySpec(raw, "AES");
			// 6.根据指定算法AES自成密码器
			Cipher cipher = Cipher.getInstance("AES");
			// 7.初始化密码器，第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作，第二个参数为使用的KEY
			cipher.init(Cipher.DECRYPT_MODE, key);
			// 8.将加密并编码后的内容解码成字节数组

			byte[] byteContent = Base64.getDecoder().decode(content);
			/*
			 * 解密
			 */
			byte[] byteDecode = cipher.doFinal(byteContent);
			return new String(byteDecode, StandardCharsets.UTF_8);
		}
		catch (IllegalBlockSizeException e) {
			throw new BusinessException("兄弟，配置文件中的密码需要使用AES加密，" + "请使用cn.chiship.sdk.core.encryption.AESUtil工具类修改这些值！");
		}
		catch (Exception e) {
			LOGGER.error("发生异常", e);
		}
		// 如果有错就返加nulll
		return null;
	}

}
